home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 2000 October / Software of the Month - Ultimate Collection Shareware 277.iso / pc / PROGRAMS / UTILITY / WINLINUX / DATA1.CAB / programs_-_kernel_source / KERNEL / RESOURCE.C < prev    next >
C/C++ Source or Header  |  1999-09-17  |  4KB  |  190 lines

  1. /*
  2.  *    linux/kernel/resource.c
  3.  *
  4.  * Copyright (C) 1995    Linus Torvalds
  5.  *            David Hinds
  6.  *
  7.  * Kernel io-region resource management
  8.  */
  9.  
  10. #include <linux/sched.h>
  11. #include <linux/errno.h>
  12. #include <linux/ioport.h>
  13. #include <linux/init.h>
  14.  
  15. #define IOTABLE_SIZE 128
  16.  
  17. typedef struct resource_entry_t {
  18.     u_long from, num;
  19.     const char *name;
  20.     struct resource_entry_t *next;
  21. } resource_entry_t;
  22.  
  23. static resource_entry_t iolist = { 0, 0, "", NULL };
  24.  
  25. static resource_entry_t iotable[IOTABLE_SIZE];
  26.  
  27. /*
  28.  * This generates the report for /proc/ioports
  29.  */
  30. int get_ioport_list(char *buf)
  31. {
  32.     resource_entry_t *p;
  33.     int len = 0;
  34.  
  35.     for (p = iolist.next; (p) && (len < 4000); p = p->next)
  36.         len += sprintf(buf+len, "%04lx-%04lx : %s\n",
  37.                p->from, p->from+p->num-1, p->name);
  38.     if (p)
  39.         len += sprintf(buf+len, "4K limit reached!\n");
  40.     return len;
  41. }
  42.  
  43. /*
  44.  * The workhorse function: find where to put a new entry
  45.  */
  46. static resource_entry_t *find_gap(resource_entry_t *root,
  47.                   u_long from, u_long num)
  48. {
  49.     unsigned long flags;
  50.     resource_entry_t *p;
  51.     
  52.     if (from > from+num-1)
  53.         return NULL;
  54.     save_flags(flags);
  55.     cli();
  56.     for (p = root; ; p = p->next) {
  57.         if ((p != root) && (p->from+p->num-1 >= from)) {
  58.             p = NULL;
  59.             break;
  60.         }
  61.         if ((p->next == NULL) || (p->next->from > from+num-1))
  62.             break;
  63.     }
  64.     restore_flags(flags);
  65.     return p;
  66. }
  67.  
  68. /*
  69.  * Call this from the device driver to register the ioport region.
  70.  */
  71. void request_region(unsigned long from, unsigned long num, const char *name)
  72. {
  73.     resource_entry_t *p;
  74.     int i;
  75.  
  76.     for (i = 0; i < IOTABLE_SIZE; i++)
  77.         if (iotable[i].num == 0)
  78.             break;
  79.     if (i == IOTABLE_SIZE)
  80.         printk("warning: ioport table is full\n");
  81.     else {
  82.         p = find_gap(&iolist, from, num);
  83.         if (p == NULL)
  84.             return;
  85.         iotable[i].name = name;
  86.         iotable[i].from = from;
  87.         iotable[i].num = num;
  88.         iotable[i].next = p->next;
  89.         p->next = &iotable[i];
  90.         return;
  91.     }
  92. }
  93.  
  94. /* 
  95.  * Call this when the device driver is unloaded
  96.  */
  97. void release_region(unsigned long from, unsigned long num)
  98. {
  99.     resource_entry_t *p, *q;
  100.  
  101.     for (p = &iolist; ; p = q) {
  102.         q = p->next;
  103.         if (q == NULL)
  104.             break;
  105.         if ((q->from == from) && (q->num == num)) {
  106.             q->num = 0;
  107.             p->next = q->next;
  108.             return;
  109.         }
  110.     }
  111. }
  112.  
  113. /*
  114.  * Call this to check the ioport region before probing
  115.  */
  116. int check_region(unsigned long from, unsigned long num)
  117. {
  118.     return (find_gap(&iolist, from, num) == NULL) ? -EBUSY : 0;
  119. }
  120.  
  121. #ifdef __sparc__   /* Why to carry unused code on other architectures? */
  122. /*
  123.  * This is for architectures with MMU-managed ports (sparc).
  124.  */
  125. unsigned long occupy_region(unsigned long base, unsigned long end,
  126.                 unsigned long num, unsigned int align, const char *name)
  127. {
  128.     unsigned long from = 0, till;
  129.     unsigned long flags;
  130.     int i;
  131.     resource_entry_t *p;        /* Scanning ptr */
  132.     resource_entry_t *p1;        /* === p->next */
  133.     resource_entry_t *s;        /* Found slot */
  134.  
  135.     if (base > end-1)
  136.         return 0;
  137.     if (num > end - base)
  138.         return 0;
  139.  
  140.     for (i = 0; i < IOTABLE_SIZE; i++)
  141.         if (iotable[i].num == 0)
  142.             break;
  143.     if (i == IOTABLE_SIZE) {
  144.         /* Driver prints a warning typically. */
  145.         return 0;
  146.     }
  147.  
  148.     save_flags(flags);
  149.     cli();
  150.     /* printk("occupy: search in %08lx[%08lx] ", base, end - base); */
  151.     s = NULL;
  152.     for (p = &iolist; p != NULL; p = p1) {
  153.         p1 = p->next;
  154.         /* Find window in list */
  155.         from = (p->from+p->num + align-1) & ~((unsigned long)align-1);
  156.         till = (p1 == NULL)? (unsigned long) (0 - (unsigned long)align): p1->from;
  157.         /* printk(" %08lx:%08lx", from, till); */
  158.         /* Clip window with base and end */
  159.         if (from < base) from = base;
  160.         if (till > end) till = end;
  161.         /* See if result is large enougth */
  162.         if (from < till && from + num < till) {
  163.             s = p;
  164.             break;
  165.         }
  166.     }
  167.     /* printk("\r\n"); */
  168.     restore_flags(flags);
  169.  
  170.     if (s == NULL)
  171.         return 0;
  172.  
  173.     iotable[i].name = name;
  174.     iotable[i].from = from;
  175.     iotable[i].num = num;
  176.     iotable[i].next = s->next;
  177.     s->next = &iotable[i];
  178.     return from;
  179. }
  180. #endif
  181.  
  182. /* Called from init/main.c to reserve IO ports. */
  183. void __init reserve_setup(char *str, int *ints)
  184. {
  185.     int i;
  186.  
  187.     for (i = 1; i < ints[0]; i += 2)
  188.         request_region(ints[i], ints[i+1], "reserved");
  189. }
  190.